home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / STRINGS / PSSTR108 / PASSTR.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1994-01-10  |  22.6 KB  |  1,108 lines

  1. {
  2.  
  3. Pascal String and Variable Procedures
  4.  
  5. Rev. 1.08
  6.  
  7. (c) Copyright 1993, Michael Gallias
  8.  
  9. Target: Real, Windows
  10.  
  11. Comment: Some procedures do work under Protected Mode, but not all of them.
  12.  
  13. To compile this with Turbo Pascal 6, simply remove the 'Const'
  14. from the procedure defintions, e.g.
  15.  
  16. Procedure MyProc(Const MyVar:MyType);
  17.  
  18. becomes
  19.  
  20. Procedure MyProc(MyVar:MyType);
  21.  
  22. }
  23.  
  24. {$V-} {$B-}
  25.  
  26. Unit PasStr;
  27.  
  28. Interface
  29.  
  30. {$IFNDEF WINDOWS}
  31.  
  32. Uses CRT,Dos;
  33.  
  34. Const
  35.   MaxXYSaves        =    5;                  {Max Number of Cursor Saves}
  36.  
  37. Type
  38.   XYType            = (CursorX,CursorY);
  39.   XYPosData         = Array[1..MaxXYSaves] of
  40.                         Array [XYType] of Byte;
  41.   KeyBufferFunction = (Clear,Save,Restore);
  42.  
  43. {$ENDIF}
  44.  
  45. Const
  46.   LeftText          =    0;
  47.   CentreText        =    1;
  48.   CenterText        =    1;
  49.   RightText         =    2;
  50.   OutSideText       =    3;
  51.  
  52. Type
  53.   TextFormats       = LeftText..RightText;
  54.   JustifyFormats    = LeftText..OutSideText;
  55.   CharSet           = Set Of Char;
  56.  
  57. {$IFDEF WINDOWS}
  58.  
  59. Procedure FSplit        (Path:String; Var Dir, Name, Ext:String);
  60.  
  61. {$ELSE}
  62.  
  63. Procedure SaveCursorSize(Var Data:Word);
  64. Procedure RestCursorSize(Data:Word);
  65. Procedure SaveXYPos     (Var Position:XYPosData);
  66. Procedure RestXYPos     (Var Position:XYPosData);
  67. Procedure CursorSize    (UpLim,DownLim:Byte);
  68.  
  69. Procedure PushCursorSize;
  70. Procedure PopCursorSize;
  71. Procedure PushXYPos;
  72. Procedure PopXYPos;
  73. Procedure PushTextColor;
  74. Procedure PopTextColor;
  75.  
  76. Procedure KeyBuffer     (Option:KeyBufferFunction);
  77.  
  78. {$IFDEF MSDOS}
  79.  
  80. Function  MemoryCount   (P:Pointer):LongInt;
  81. Procedure GetLowestOfs  (P:Pointer; Var S,O:Word);
  82. Procedure AdjustPtr     (Var P:Pointer; Amount:LongInt);
  83.  
  84. {$ENDIF}
  85.  
  86. {$ENDIF}
  87.  
  88. Procedure SpacesToZeros (StIn:String; Var StOut:String);
  89. Procedure RemoveLeading (StIn:String; Var StOut:String;
  90.                          Const RemoveSet:CharSet);
  91. Function  PosFrom       (SubS:String; StIn:String; FarIn:Byte):Byte;
  92. Function  RevPosFrom    (SubS:String; StIn:String; FarIn:Byte):Byte;
  93. Procedure UpperCase     (StIn:String; Var StOut:String);
  94. Procedure LowerCase     (StIn:String; Var StOut:String);
  95. Procedure CapWords      (StIn:String; Var StOut:String);
  96. Procedure PadVar        (StIn:String; Var StOut:String; Count:Byte);
  97. Procedure PadVarWith    (StIn:String; Var StOut:String; Count:Byte;
  98.                          WithMe:Char);
  99. Procedure PadFileName   (StIn:String; Var StOut:String);
  100. Procedure FormatVar     (StIn:String; Var StOut:String;
  101.                          Size:Byte; Format:TextFormats);
  102. Procedure UnPadVar      (StIn:String; Var StOut:String);
  103. Procedure UnPadVarRight (StIn:String; Var StOut:String);
  104. Procedure UnPadVarLeft  (StIn:String; Var StOut:String);
  105. Procedure RightJustify  (StIn:String; Var StOut:String;
  106.                          Margin:Byte; JType:JustifyFormats);
  107.  
  108. Procedure ByteToHex     (Decimal:Byte; Var Hex:String);
  109. Procedure WordToHex     (Decimal:Word; Var Hex:String);
  110. Procedure LongIntToHex  (Decimal:LongInt; Var Hex:String);
  111.  
  112. Function  HexDigitValue (HexDigit:Char):Byte;
  113. Procedure HexToByte     (Hex:String; Var Decimal:Byte; Var Code:Integer);
  114. Procedure HexToWord     (Hex:String; Var Decimal:Word; Var Code:Integer);
  115. Procedure HexToLongInt  (Hex:String; Var Decimal:LongInt; Var Code:Integer);
  116.  
  117. Function  Min           (I, J:LongInt):LongInt;
  118. Function  Max           (I, J:LongInt):LongInt;
  119.  
  120. Function  AdjustMeter   (StartMeter1,EndMeter1,ValueMeter1,
  121.                          StartMeter2,EndMeter2:LongInt):LongInt;
  122.  
  123. Procedure SwapBytes     (Var A,B:Byte);
  124. Procedure SwapIntegers  (Var A,B:Integer);
  125. Procedure SwapWords     (Var A,B:Word);
  126. Procedure SwapLongInts  (Var A,B:LongInt);
  127. Procedure SwapReals     (Var A,B:Real);
  128. Procedure SwapStrings   (Var A,B:String);
  129.  
  130. {$IFOPT N+}
  131.  
  132. Procedure SwapSingles   (Var A,B:Single);
  133. Procedure SwapDoubles   (Var A,B:Double);
  134. Procedure SwapExtendeds (Var A,B:Extended);
  135. Procedure SwapComps     (Var A,B:Comp);
  136.  
  137. {$ENDIF}
  138.  
  139. Implementation
  140.  
  141. {$IFDEF WINDOWS}
  142.  
  143. Procedure FSplit(Path:String; Var Dir, Name, Ext:String);
  144.  
  145. Var
  146.   LastSlash  :Byte;
  147.  
  148. Begin
  149.   LastSlash:=RevPosFrom('\',Path,Length(Path));
  150.   If LastSlash=0 Then
  151.   Begin
  152.     LastSlash:=RevPosFrom(':',Path,Length(Path));
  153.     If LastSlash>0 Then
  154.     Begin                               {Found a Drive with Default Path}
  155.       Dir:=Copy(Path,1,LastSlash);
  156.       Delete(Path,1,LastSlash);
  157.       LastSlash:=0;
  158.     End
  159.     Else                                {No Drive, No Path}
  160.       Dir:='';
  161.   End
  162.   Else
  163.   Begin                                 {A Path Found}
  164.     Dir:=Copy(Path,1,LastSlash);
  165.     Delete(Path,1,LastSlash);           {Delete Directory}
  166.   End;
  167.  
  168.   LastSlash:=Pos('.',Path);
  169.   If LastSlash>0 Then
  170.   Begin
  171.     Name:=Copy(Path,1,LastSlash-1);
  172.     Ext:=Copy(Path,LastSlash,Length(Path)-(LastSlash-1));
  173.   End
  174.   Else
  175.   Begin
  176.     Name:=Path;
  177.     Ext:='';
  178.   End;
  179.   If Length(Name)>8 Then Name:=Copy(Name,1,8);
  180.   If Length(Ext)>4 Then Ext:=Copy(Ext,1,4);
  181. End;
  182.  
  183. {$ELSE}
  184.  
  185. Var
  186.   PushPopCursorSize:Array[1..MaxXYSaves] of Word;
  187.   PushPopTextColor :Array[1..MaxXYSaves] of Word;
  188.   PushPopCursorPos :XYPosData;
  189.  
  190. Procedure SaveCursorSize(Var Data:Word); Assembler;
  191. Asm
  192.   mov  ah,3
  193.   int  10h
  194.   les  di,Data
  195.   mov  es:[di],cx
  196. End;
  197.  
  198. Procedure RestCursorSize(Data:Word); Assembler;
  199. Asm
  200.   mov  ah,1
  201.   mov  cx,Data
  202.   int  10h
  203. End;
  204.  
  205. Procedure SaveXYPos(Var Position:XYPosData);
  206. {This saves the current cursor position and can store up to the last five}
  207. {cursor positions}
  208. {Number 'MaxXYSaves' is the lastest save}
  209.  
  210. Var
  211.   X:Byte;   {Loop}
  212.  
  213. Begin
  214.   For X:=1 to MaxXYSaves-1 do                    {Shift Cursor Saves up}
  215.   Begin
  216.       Position[X,CursorX]:=Position[X+1,CursorX];
  217.       Position[X,CursorY]:=Position[X+1,CursorY];
  218.   End;   {For X Loop}
  219.   Position[5,CursorX]:=WhereX;      {Insert New Cursor Save Position}
  220.   Position[5,CursorY]:=WhereY;
  221. End;  {SaveXYPos}
  222.  
  223. Procedure RestXYPos(Var Position:XYPosData);
  224. {This will restore up to five previously saved cursor positions}
  225. {Number 'MaxXYSaves' is the position to be restored}
  226.  
  227. Var
  228.   X:Byte;       {Loop}
  229.  
  230. Begin
  231.   GotoXY(Position[MaxXYSaves,CursorX],Position[MaxXYSaves,CursorY]); {Goto Old Position}
  232.   For X:=MaxXYSaves downto 2 do    {Shift up the cursor positions for the next restore}
  233.   Begin
  234.       Position[X,CursorX]:=Position[X-1,CursorX];
  235.       Position[X,CursorY]:=Position[X-1,CursorY];
  236.   End;  {For X Loop}
  237. End;  {RestXYPos}
  238.  
  239. Procedure CursorSize(UpLim,DownLim:Byte); Assembler;
  240. {Set the cursor size.  Send $20,$20 for no cursor}
  241. Asm
  242.   mov  ah,1
  243.   mov  ch,UpLim
  244.   mov  cl,DownLim
  245.   int  10h
  246. End;
  247.  
  248. Procedure PushCursorSize;
  249.  
  250. Var
  251.   X:Word;
  252.  
  253. Begin
  254.   For X:=1 to MaxXYSaves-1 do
  255.     PushPopCursorSize[X]:=PushPopCursorSize[X+1];
  256.  
  257.   Asm
  258.     mov  ah,3
  259.     int  10h
  260.     mov  X,cx
  261.   End;
  262.  
  263.   PushPopCursorSize[MaxXYSaves]:=X;
  264. End;
  265.  
  266. Procedure PopCursorSize;
  267.  
  268. Var
  269.   X:Word;
  270.  
  271. Begin
  272.   X:=PushPopCursorSize[MaxXYSaves];
  273.  
  274.   Asm
  275.     mov  ah,1
  276.     mov  cx,X
  277.     int  10h
  278.   End;
  279.  
  280.   For X:=MaxXYSaves DownTo 2 do
  281.     PushPopCursorSize[X]:=PushPopCursorSize[X-1];
  282. End;
  283.  
  284. Procedure PushXYPos;
  285.  
  286. Var
  287.   X:Byte;
  288.  
  289. Begin
  290.   For X:=1 to MaxXYSaves-1 do
  291.     PushPopCursorPos[X]:=PushPopCursorPos[X+1];
  292.  
  293.   PushPopCursorPos[MaxXYSaves,CursorX]:=WhereX;
  294.   PushPopCursorPos[MaxXYSaves,CursorY]:=WhereY;
  295. End;
  296.  
  297. Procedure PopXYPos;
  298.  
  299. Var
  300.   X:Byte;
  301.  
  302. Begin
  303.   GotoXY(PushPopCursorPos[MaxXYSaves,CursorX],
  304.          PushPopCursorPos[MaxXYSaves,CursorY]);
  305.  
  306.   For X:=MaxXYSaves DownTo 2 do
  307.     PushPopCursorPos[X]:=PushPopCursorPos[X-1];
  308. End;
  309.  
  310. Procedure PushTextColor;
  311.  
  312. Var
  313.   X:Byte;
  314.  
  315. Begin
  316.   For X:=1 to MaxXYSaves-1 do
  317.     PushPopTextColor[X]:=PushPopTextColor[X+1];
  318.  
  319.   PushPopTextColor[MaxXYSaves]:=TextAttr;
  320. End;
  321.  
  322. Procedure PopTextColor;
  323.  
  324. Var
  325.   X:Word;
  326.  
  327. Begin
  328.   TextAttr:=PushPopTextColor[MaxXYSaves];
  329.  
  330.   For X:=MaxXYSaves DownTo 2 do
  331.     PushPopTextColor[X]:=PushPopTextColor[X-1];
  332. End;
  333.  
  334. Procedure KeyBuffer(Option:KeyBufferFunction);
  335.  
  336. Type
  337.   KeyBufType=Record
  338.                Head:Word;
  339.                Tail:Word;
  340.                Data:Array[1..16] Of Word;
  341.              End;
  342.  
  343. Const
  344.   KeyBuf:KeyBufType=(Head:0;Tail:0;Data:(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0));
  345.  
  346. Var
  347.   P     :Pointer;
  348.  
  349. Begin
  350.   P:=Ptr(Seg0040,$1A);
  351.   Case Option Of
  352.     Clear   :MemW[Seg0040:$1A]:=MemW[Seg0040:$1C];
  353.     Save    :Move(P^,KeyBuf,SizeOf(KeyBuf));
  354.     Restore :Move(KeyBuf,P^,SizeOf(KeyBuf));
  355.   End;
  356. End;
  357.  
  358. Function MemoryCount(P:Pointer):LongInt;
  359. Begin
  360.   MemoryCount:=LongInt(Seg(P^)) * 16 + Ofs(P^);
  361. End;
  362.  
  363. Procedure GetLowestOfs(P:Pointer;Var S,O:Word);
  364. Begin
  365.   O:=Ofs(P^);
  366.   S:=Seg(P^);
  367.   If O<16 Then Exit;
  368.   Inc(S,O Div 16);
  369.   O:=O Mod 16;
  370. End;
  371.  
  372. Procedure AdjustPtr(Var P:Pointer;Amount:LongInt);
  373.  
  374. Var
  375.   X,
  376.   Segt,
  377.   Ofst  :Word;
  378.  
  379. Begin
  380.   Segt:=Seg(P^);
  381.   Ofst:=Ofs(P^);
  382.   If Amount<0 Then
  383.   Begin
  384.     X:=$FFFF-Ofst;      {Want to Make Ofst as Big as Possible}
  385.     X:=X - (X Mod 16);  {Round It to the Nearest 16}
  386.     Dec(Segt,X Div 16); {Take it from the Segment}
  387.     Inc(Ofst,X);        {Add it to the Offset}
  388.   End
  389.   Else
  390.   Begin
  391.     X:=Ofst - (Ofst Mod 16);    {Want to make Ofst as Small as Possible}
  392.     Inc(Segt,X Div 16);         {Add it to the Segment}
  393.     Dec(Ofst,X);                {Take it from the Offset}
  394.   End;
  395.   P:=Ptr(Segt,Ofst+Amount);
  396. End;
  397.  
  398. {$ENDIF}
  399.  
  400. Procedure SpacesToZeros(StIn:String;Var StOut:String); Assembler;
  401.  
  402. Asm
  403.   push  ds
  404.   cld
  405.   lds   si,StIn
  406.   les   di,StOut
  407.   lodsb
  408.   stosb
  409.   xor   ah,ah
  410.   xchg  ax,cx
  411.   jcxz  @Section3
  412.  
  413. @Section1:
  414.  
  415.   lodsb
  416.   cmp   al,' '
  417.   jne   @Section2
  418.   mov   al,'0'
  419.  
  420. @Section2:
  421.  
  422.   stosb
  423.   loop  @Section1
  424.  
  425. @Section3:
  426.  
  427.   pop   ds
  428.  
  429. End;
  430.  
  431. Procedure RemoveLeading(StIn:String; Var StOut:String;
  432.                         Const RemoveSet:CharSet);
  433.  
  434. Var
  435.   X     :Byte;
  436.  
  437. Begin
  438.   X:=1;
  439.   While (X<=Length(StIn)) And (StIn[X] in RemoveSet) do
  440.     Inc(X);
  441.   StOut:=Copy(StIn,X,Length(StIn)-X+1);
  442. End;
  443.  
  444. Function PosFrom(SubS:String;StIn:String;FarIn:Byte):Byte;
  445.  
  446. Var
  447.   NewPos:Byte;
  448.  
  449. Begin
  450.   Delete(StIn,1,FarIn-1);
  451.   NewPos:=Pos(SubS,StIn);
  452.   If NewPos=0 Then
  453.     PosFrom:=0
  454.   Else
  455.     PosFrom:=NewPos+FarIn-1;
  456. End;
  457.  
  458. Function RevPosFrom(SubS:String;StIn:String;FarIn:Byte):Byte;
  459.  
  460. Var
  461.   Mark  :Byte;
  462.   Temp  :Byte;
  463.   Chk   :String;
  464.  
  465. Begin
  466.   If Length(SubS)>Length(StIn) Then
  467.   Begin
  468.     RevPosFrom:=0;
  469.     Exit;
  470.   End;
  471.  
  472.   Mark:=Length(StIn)-Length(SubS)+1;
  473.   If Mark>FarIn Then Mark:=FarIn;
  474.   Temp:=0;
  475.  
  476.   While (Mark>=1) And (Temp=0) do
  477.   Begin
  478.     Chk:=Copy(StIn,Mark,Length(SubS));
  479.     If Chk=SubS Then
  480.       Temp:=Mark
  481.     Else
  482.       Dec(Mark);
  483.   End;
  484.   RevPosFrom:=Temp;
  485. End;
  486.  
  487. Procedure UpperCase(StIn:String;Var StOut:String); Assembler;
  488.  
  489. Asm
  490.   push  ds
  491.   cld
  492.   lds   si,StIn
  493.   les   di,StOut
  494.   lodsb
  495.   stosb
  496.   xor   ah,ah
  497.   xchg  ax,cx
  498.   jcxz  @Section3
  499.  
  500. @Section1:
  501.  
  502.   lodsb
  503.   cmp   al,'a'
  504.   jb    @Section2
  505.   cmp   al,'z'
  506.   ja    @Section2
  507.   sub   al,20h
  508.  
  509. @Section2:
  510.  
  511.   stosb
  512.   loop  @Section1
  513.  
  514. @Section3:
  515.  
  516.   pop   ds
  517.  
  518. End;
  519.  
  520. Procedure LowerCase(StIn:String;Var StOut:String); Assembler;
  521.  
  522. Asm
  523.   push  ds
  524.   cld
  525.   lds   si,StIn
  526.   les   di,StOut
  527.   lodsb
  528.   stosb
  529.   xor   ah,ah
  530.   xchg  ax,cx
  531.   jcxz  @Section3
  532.  
  533. @Section1:
  534.  
  535.   lodsb
  536.   cmp   al,'A'
  537.   jb    @Section2
  538.   cmp   al,'Z'
  539.   ja    @Section2
  540.   add   al,20h
  541.  
  542. @Section2:
  543.  
  544.   stosb
  545.   loop  @Section1
  546.  
  547. @Section3:
  548.  
  549.   pop   ds
  550.  
  551. End;
  552.  
  553. Procedure CapWords(StIn:String;Var StOut:String);
  554.  
  555. Var
  556.   LastSpace  :Boolean;
  557.   X          :Byte;
  558.  
  559. Begin
  560.   StOut:=StIn;
  561.   LastSpace:=True;
  562.   For X:=1 to Length(StOut) do
  563.   Begin
  564.     If LastSpace Then StOut[X]:=UpCase(StOut[X]);
  565.  
  566.     If StOut[X]=' ' Then
  567.       LastSpace:=True
  568.     Else
  569.       LastSpace:=False;
  570.   End;
  571. End;
  572.  
  573. Procedure PadVar(StIn:String;Var StOut:String;Count:Byte);
  574.  
  575. Var
  576.    J:Byte;
  577.  
  578. Begin
  579.   StOut:=StIn;
  580.   For J:=1 to Count do
  581.     StOut:=StOut+' ';
  582. End;
  583.  
  584. Procedure PadVarWith(StIn:String;Var StOut:String;Count:Byte;WithMe:Char);
  585.  
  586. Var
  587.    J:Byte;
  588.  
  589. Begin
  590.   StOut:=StIn;
  591.   For J:=1 to Count do
  592.     StOut:=StOut+WithMe;
  593. End;
  594.  
  595. Procedure PadFileName(StIn:String;Var StOut:String);
  596.  
  597. {Pads a file name to 12 characters.}
  598.  
  599. Var
  600.   T1, T2, T3 :String;
  601.   Dot        :Char;
  602.  
  603. Begin
  604.   If StIn='.' Then
  605.   Begin
  606.     PadVar(StIn,StOut,11);
  607.     Exit;
  608.   End;
  609.  
  610.   If StIn='..' Then
  611.   Begin
  612.     PadVar(StIn,StOut,10);
  613.     Exit;
  614.   End;
  615.  
  616.   FSplit(StIn,T1,T2,T3);
  617.   PadVar(T2,T2,8-Length(T2));
  618.   Delete(T3,1,1);
  619.   PadVar(T3,T3,3-Length(T3));
  620.   If T3='   ' Then Dot:=' ' Else Dot:='.';
  621.   StOut:=T1+T2+Dot+T3;
  622. End;
  623.  
  624. Procedure FormatVar(StIn:String;Var StOut:String;
  625.                     Size:Byte;Format:TextFormats);
  626. Begin
  627.   StOut:=StIn;
  628.  
  629.   If Format=LeftText Then
  630.     While Length(StOut)<Size do
  631.       StOut:=StOut+' '
  632.   Else
  633.     If Format=CentreText Then
  634.     Begin
  635.       While Length(StOut)<Size-1 do
  636.         StOut:=' '+StOut+' ';
  637.       Format:=RightText;
  638.     End;
  639.  
  640.   If Format=RightText Then
  641.     While Length(StOut)<Size do
  642.       StOut:=' '+StOut;
  643. End;
  644.  
  645. Procedure UnPadVar(StIn:String;Var StOut:String);
  646. Begin
  647.   StOut:=StIn;
  648.   While (Length(StOut)>0) And (StOut[1]=' ') do
  649.     Delete(StOut,1,1);
  650.   While (Length(StOut)>0) And (StOut[Length(StOut)]=' ') do
  651.     Delete(StOut,Length(StOut),1);
  652. End;
  653.  
  654. Procedure UnPadVarRight(StIn:String;Var StOut:String);
  655. Begin
  656.   StOut:=StIn;
  657.   While (Length(StOut)>0) And (StOut[Length(StOut)]=' ') do
  658.     Delete(StOut,Length(StOut),1);
  659. End;
  660.  
  661. Procedure UnPadVarLeft(StIn:String;Var StOut:String);
  662. Begin
  663.   StOut:=StIn;
  664.   While (Length(StOut)>0) And (StOut[1]=' ') do
  665.     Delete(StOut,1,1);
  666. End;
  667.  
  668. Procedure RightJustify(StIn:String;Var StOut:String;
  669.                        Margin:Byte;JType:JustifyFormats);
  670.  
  671.   Procedure RightJustifyLeft;
  672.  
  673.   Var
  674.     EndLoop  :Boolean;
  675.     Marker,
  676.     SpPos    :Byte;
  677.  
  678.   Begin
  679.     EndLoop:=False;
  680.     While (Length(StOut)<Margin) And (Not EndLoop) do
  681.     Begin
  682.       Marker:=1;
  683.       Repeat
  684.         SpPos:=PosFrom(' ',StOut,Marker);
  685.         If (SpPos=0) Or (SpPos=Length(StOut)) Then
  686.         Begin
  687.           If Marker=1 Then EndLoop:=True;
  688.           Marker:=255
  689.         End
  690.         Else
  691.         Begin
  692.           Insert(' ',StOut,SpPos);
  693.           Marker:=SpPos+2;
  694.           While (StOut[Marker]=' ') And (Marker<Margin) do
  695.             Inc(Marker);
  696.         End;
  697.       Until (Length(StOut)>=Margin) Or (Marker>Length(StOut)) Or EndLoop;
  698.     End;
  699.   End;
  700.  
  701.   Procedure RightJustifyRight;
  702.  
  703.   Var
  704.     EndLoop  :Boolean;
  705.     Marker,
  706.     SpPos    :Byte;
  707.  
  708.   Begin
  709.     EndLoop:=False;
  710.     While (Length(StOut)<Margin) And (Not EndLoop) do
  711.     Begin
  712.       Marker:=Length(StOut);
  713.       Repeat
  714.         SpPos:=RevPosFrom(' ',StOut,Marker);
  715.         If (SpPos=0) Or (SpPos=1) Then
  716.         Begin
  717.           If Marker=Length(StOut) Then EndLoop:=True;
  718.           Marker:=0;
  719.         End
  720.         Else
  721.         Begin
  722.           Insert(' ',StOut,SpPos);
  723.           Marker:=SpPos-1;
  724.           While (StOut[Marker]=' ') And (Marker>1) do
  725.             Dec(Marker);
  726.         End;
  727.       Until (Length(StOut)>=Margin) Or (Marker=0) Or EndLoop;
  728.     End;
  729.   End;
  730.  
  731.   Procedure RightJustifyCentre;
  732.  
  733.   Var
  734.     EndLoop1,
  735.     EndLoop2 :Boolean;
  736.     Marker1,
  737.     Marker2,
  738.     SpPos    :Byte;
  739.  
  740.   Begin
  741.     EndLoop1:=False;
  742.     EndLoop2:=False;
  743.  
  744.     While (Length(StOut)<Margin) And (Not EndLoop1) And (Not EndLoop2) do
  745.     Begin
  746.       Marker1:=Length(StOut) Div 2;
  747.       Marker2:=Marker1;
  748.       If StOut[Marker1]=' ' Then Inc(Marker1);
  749.  
  750.       Repeat
  751.         If Not ((Length(StOut)>=Margin) Or (Marker1>Length(StOut)) Or EndLoop1) Then
  752.         Begin
  753.           SpPos:=PosFrom(' ',StOut,Marker1);
  754.           If (SpPos=0) Or (SpPos=Length(StOut)) Then
  755.           Begin
  756.             If Marker1=Length(StOut) Div 2 Then EndLoop1:=True;
  757.             Marker1:=255
  758.           End
  759.           Else
  760.           Begin
  761.             Insert(' ',StOut,SpPos);
  762.             Marker1:=SpPos+2;
  763.             While (StOut[Marker1]=' ') And (Marker1<Margin) do
  764.               Inc(Marker1);
  765.           End;
  766.         End;
  767.  
  768.         If Not ((Length(StOut)>=Margin) Or (Marker2=0) Or EndLoop2) Then
  769.         Begin
  770.           SpPos:=RevPosFrom(' ',StOut,Marker2);
  771.           If (SpPos<=1) Then
  772.           Begin
  773.             If Marker2=Length(StOut) Div 2 Then EndLoop2:=True;
  774.             Marker2:=0;
  775.           End
  776.           Else
  777.           Begin
  778.             Insert(' ',StOut,SpPos);
  779.             If Marker1 <> 255 Then
  780.               Inc(Marker1);               {Pushes Marker 1 Up 1 Space}
  781.             Marker2:=SpPos-1;
  782.             While (StOut[Marker2]=' ') And (Marker2>1) do
  783.               Dec(Marker2);
  784.           End;
  785.         End;
  786.       Until ((Length(StOut)>=Margin) Or (Marker1>Length(StOut)) Or EndLoop1) And
  787.             ((Length(StOut)>=Margin) Or (Marker2=0) Or EndLoop2);
  788.     End;
  789.   End;
  790.  
  791.   Procedure RightJustifyOutSide;
  792.  
  793.   Var
  794.     EndLoop1,
  795.     EndLoop2 :Boolean;
  796.     Marker1,
  797.     Marker2,
  798.     SpPos    :Byte;
  799.  
  800.   Begin
  801.     EndLoop1:=False;
  802.     EndLoop2:=False;
  803.  
  804.     While (Length(StOut)<Margin) And (Not EndLoop1) And (Not EndLoop2) do
  805.     Begin
  806.       Marker1:=1;
  807.       Marker2:=Length(StOut);
  808.  
  809.       Repeat
  810.         If Not ((Length(StOut)>=Margin) Or (Marker1>Length(StOut) Div 2) Or EndLoop1) Then
  811.         Begin
  812.           SpPos:=PosFrom(' ',StOut,Marker1);
  813.           If (SpPos=0) Or (SpPos>Length(StOut) Div 2) Then
  814.           Begin
  815.             If Marker1=1 Then EndLoop1:=True;
  816.             Marker1:=255
  817.           End
  818.           Else
  819.           Begin
  820.             Insert(' ',StOut,SpPos);
  821.             Marker1:=SpPos+2;
  822.             While (StOut[Marker1]=' ') And (Marker1<Length(StOut) Div 2) do
  823.               Inc(Marker1);
  824.           End;
  825.         End;
  826.  
  827.         If Not ((Length(StOut)>=Margin) Or (Marker2<Length(StOut) Div 2) Or EndLoop2) Then
  828.         Begin
  829.           SpPos:=RevPosFrom(' ',StOut,Marker2);
  830.           If (SpPos<=1) Then
  831.           Begin
  832.             If Marker2<=Length(StOut) Div 2 Then EndLoop2:=True;
  833.             Marker2:=0;
  834.           End
  835.           Else
  836.           Begin
  837.             Insert(' ',StOut,SpPos);
  838.             If Marker1 <> 255 Then
  839.               Inc(Marker1);               {Pushes Marker 1 Up 1 Space}
  840.             Marker2:=SpPos-1;
  841.             While (StOut[Marker2]=' ') And (Marker2>=Length(StOut) Div 2) do
  842.               Dec(Marker2);
  843.           End;
  844.         End;
  845.       Until ((Length(StOut)>=Margin) Or (Marker1>Length(StOut) Div 2) Or EndLoop1) And
  846.             ((Length(StOut)>=Margin) Or (Marker2<=Length(StOut) Div 2) Or EndLoop2);
  847.     End;
  848.   End;
  849.  
  850. Begin
  851.   StOut:=StIn;
  852.   Case JType Of
  853.     LeftText    :RightJustifyLeft;
  854.     RightText   :RightJustifyRight;
  855.     CentreText  :RightJustifyCentre;
  856.     OutSideText :RightJustifyOutSide;
  857.   End;
  858. End;
  859.  
  860. Procedure ByteToHex(Decimal:Byte; Var Hex:String);
  861.  
  862. Var
  863.   X     :Byte;
  864.  
  865. Begin
  866.   Hex[0]:=#2;
  867.   X:=Decimal Div 16;
  868.   Case X Of
  869.      0 ..  9  :Hex[1]:=Chr(Ord('0')+X);
  870.     10 .. 15  :Hex[1]:=Chr(Ord('A')+X-10);
  871.   End;
  872.   X:=Decimal Mod 16;
  873.   Case X Of
  874.      0 ..  9  :Hex[2]:=Chr(Ord('0')+X);
  875.     10 .. 15  :Hex[2]:=Chr(Ord('A')+X-10);
  876.   End;
  877. End;
  878.  
  879. Procedure WordToHex(Decimal:Word; Var Hex:String);
  880.  
  881. Var
  882.   P1, P2        :String[2];
  883.  
  884. Begin
  885.   ByteToHex(Hi(Decimal),P1);
  886.   ByteToHex(Lo(Decimal),P2);
  887.   Hex:=P1+P2;
  888. End;
  889.  
  890. Procedure LongIntToHex(Decimal:LongInt; Var Hex:String);
  891.  
  892. Var
  893.   T     :String[2];
  894.   B     :Byte;
  895.   x     :Byte;
  896.  
  897. Begin
  898.   Hex:='';
  899.   For x:=1 to 4 do
  900.   Begin
  901.     B:=(Decimal Shl ( (x-1) * 8 )) And 255;
  902.     ByteToHex(B,T);
  903.     Hex:=Hex+T;
  904.   End;
  905. End;
  906.  
  907. Function HexDigitValue(HexDigit:Char):Byte;
  908.  
  909. {Value of an UPPERCASE Hex Digit}
  910.  
  911. Begin
  912.   Case HexDigit Of
  913.     '0'..'9'  :HexDigitValue:=Ord(HexDigit)-Ord('0');
  914.     'A'..'F'  :HexDigitValue:=Ord(HexDigit)-Ord('A') + 10;
  915.   End;
  916. End;
  917.  
  918. Procedure HexToByte(Hex:String; Var Decimal:Byte; Var Code:Integer);
  919.  
  920. Var
  921.   X     :LongInt;
  922.  
  923. Begin
  924.   HexToLongInt(Hex, X, Code);
  925.   If Code=0 Then
  926.     If (X>=0) And (X<=255) Then Decimal:=X Else Code:=254;
  927. End;
  928.  
  929. Procedure HexToWord(Hex:String; Var Decimal:Word; Var Code:Integer);
  930.  
  931. Var
  932.   X     :LongInt;
  933.  
  934. Begin
  935.   HexToLongInt(Hex, X, Code);
  936.   If Code=0 Then
  937.     If (X>=0) And (X<=65535) Then Decimal:=X Else Code:=254;
  938. End;
  939.  
  940. Procedure HexToLongInt(Hex:String; Var Decimal:LongInt; Var Code:Integer);
  941.  
  942. Var
  943.   x,y   :Byte;
  944.  
  945. Begin
  946.   Code:=0;
  947.   If Hex[1]='$' Then Delete(Hex,1,1);
  948.   If UpCase(Hex[Length(Hex)])='H' Then Delete(Hex,Length(Hex),1);
  949.  
  950.   UpperCase(Hex,Hex);
  951.   For x:=1 to Length(Hex) do
  952.     If Not (Hex[x] in ['0'..'9','A'..'F']) Then Code:=X;
  953.  
  954.   If Length(Hex)>8 Then Code:=255;
  955.   If Code=0 Then
  956.   Begin
  957.     Decimal:=0;
  958.     y:=0;
  959.     For x:=Length(Hex) downto 1 do
  960.     Begin
  961.       Decimal:=Decimal Or (HexDigitValue(Hex[x]) Shl y);
  962.       Inc(y,4);
  963.     End;
  964.   End;
  965. End;
  966.  
  967. Function Min(I, J:LongInt):LongInt;
  968. Begin
  969.   If I>J Then Min:=J Else Min:=I;
  970. End;
  971.  
  972. Function Max(I, J:LongInt):LongInt;
  973. Begin
  974.   If I>J Then Max:=I Else Max:=J;
  975. End;
  976.  
  977. Function AdjustMeter(StartMeter1,EndMeter1,ValueMeter1,
  978.                      StartMeter2,EndMeter2:LongInt):LongInt;
  979. Begin
  980.   AdjustMeter:=(((EndMeter2-StartMeter2)*(ValueMeter1-StartMeter1)) Div
  981.                (EndMeter1-StartMeter1))+StartMeter2;
  982. End;
  983.  
  984. Procedure SwapBytes(Var A,B:Byte); Assembler;
  985. Asm
  986.   push  ds
  987.   les   di,A
  988.   lds   si,B
  989.   mov   al,es:[di]
  990.   mov   bl,al             {A into BX}
  991.   mov   al,ds:[si]        {B into AX}
  992.   mov   es:[di],al
  993.   mov   al,bl
  994.   mov   ds:[si],al
  995.   pop   ds
  996. End;
  997.  
  998. Procedure SwapIntegers(Var A,B:Integer); Assembler;
  999. Asm
  1000.   push  ds
  1001.   les   di,A
  1002.   lds   si,B
  1003.   mov   ax,es:[di]
  1004.   mov   bx,ax             {A into BX}
  1005.   mov   ax,ds:[si]        {B into AX}
  1006.   mov   es:[di],ax
  1007.   mov   ax,bx
  1008.   mov   ds:[si],ax
  1009.   pop   ds
  1010. End;
  1011.  
  1012. Procedure SwapWords(Var A,B:Word); Assembler;
  1013. Asm
  1014.   push  ds
  1015.   les   di,A
  1016.   lds   si,B
  1017.   mov   ax,es:[di]
  1018.   mov   bx,ax             {A into BX}
  1019.   mov   ax,ds:[si]        {B into AX}
  1020.   mov   es:[di],ax
  1021.   mov   ax,bx
  1022.   mov   ds:[si],ax
  1023.   pop   ds
  1024. End;
  1025.  
  1026. Procedure SwapLongInts(Var A,B:LongInt);
  1027.  
  1028. Var
  1029.   C:LongInt;
  1030.  
  1031. Begin
  1032.   C:=A;
  1033.   A:=B;
  1034.   B:=C;
  1035. End;
  1036.  
  1037. Procedure SwapReals(Var A,B:Real);
  1038.  
  1039. Var
  1040.   C:Real;
  1041.  
  1042. Begin
  1043.   C:=A;
  1044.   A:=B;
  1045.   B:=C;
  1046. End;
  1047.  
  1048. Procedure SwapStrings(Var A,B:String);
  1049.  
  1050. Var
  1051.   C:String;
  1052.  
  1053. Begin
  1054.   C:=A;
  1055.   A:=B;
  1056.   B:=C;
  1057. End;
  1058.  
  1059. {$IFOPT N+}
  1060.  
  1061. Procedure SwapSingles(Var A,B:Single);
  1062.  
  1063. Var
  1064.   C:Single;
  1065.  
  1066. Begin
  1067.   C:=A;
  1068.   A:=B;
  1069.   B:=C;
  1070. End;
  1071.  
  1072. Procedure SwapDoubles(Var A,B:Double);
  1073.  
  1074. Var
  1075.   C:Double;
  1076.  
  1077. Begin
  1078.   C:=A;
  1079.   A:=B;
  1080.   B:=C;
  1081. End;
  1082.  
  1083. Procedure SwapExtendeds(Var A,B:Extended);
  1084.  
  1085. Var
  1086.   C:Extended;
  1087.  
  1088. Begin
  1089.   C:=A;
  1090.   A:=B;
  1091.   B:=C;
  1092. End;
  1093.  
  1094. Procedure SwapComps(Var A,B:Comp);
  1095.  
  1096. Var
  1097.   C:Comp;
  1098.  
  1099. Begin
  1100.   C:=A;
  1101.   A:=B;
  1102.   B:=C;
  1103. End;
  1104.  
  1105. {$ENDIF}
  1106.  
  1107. End.
  1108.